package com.study.common.utils;

import java.beans.IntrospectionException;
import java.beans.PropertyDescriptor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;

import com.study.common.ztree.TreeCheckBoxEntity;

import net.sf.json.JSONArray;

public class JsonTreeCheckBoxUtil {

	public static void main(String[] args) {
		/* 测试类型二 */
		TreeCheckBoxEntity t1 = new TreeCheckBoxEntity("0", "节点1", null, "true");
		TreeCheckBoxEntity t2 = new TreeCheckBoxEntity("1", "节点11", "0", "true");
		TreeCheckBoxEntity t3 = new TreeCheckBoxEntity("2", "节点12", "0", "true");
		TreeCheckBoxEntity t4 = new TreeCheckBoxEntity("4", "节点21", "3", "true");
		TreeCheckBoxEntity t6 = new TreeCheckBoxEntity("5", "节点22", "3", "true");
		TreeCheckBoxEntity t5 = new TreeCheckBoxEntity("3", "节点2", null, "true");
		TreeCheckBoxEntity t7 = new TreeCheckBoxEntity("7", "节点3", null, "true");
		TreeCheckBoxEntity t8 = new TreeCheckBoxEntity("8", "节点31", "7", "true");
		TreeCheckBoxEntity t9 = new TreeCheckBoxEntity("9", "节点311", "8", "true");
		TreeCheckBoxEntity t10 = new TreeCheckBoxEntity("10", "节点3111", "9", "false");
		List<Object> list = new ArrayList<Object>();
		list.add(t1);
		list.add(t2);
		list.add(t3);
		list.add(t4);
		list.add(t5);
		list.add(t6);
		list.add(t7);
		list.add(t8);
		list.add(t9);
		list.add(t10);
		try {
			System.out.println(
					JSONArray.fromObject(getTreeJsonStrNormal(new String[] { "id", "name", "pro", "checked" }, list)));
		} catch (IllegalArgumentException e) {
			e.printStackTrace();
		} catch (IllegalAccessException e) {
			e.printStackTrace();
		} catch (SecurityException e) {
			e.printStackTrace();
		} catch (ClassNotFoundException e) {
			e.printStackTrace();
		} catch (NoSuchMethodException e) {
			e.printStackTrace();
		} catch (InvocationTargetException e) {
			e.printStackTrace();
		} catch (IntrospectionException e) {
			e.printStackTrace();
		}

	}

	public static String getTreeJsonStrNormal(String[] members, List<Object> data)
			throws IllegalArgumentException, IllegalAccessException, SecurityException, ClassNotFoundException,
			NoSuchMethodException, InvocationTargetException, IntrospectionException {
		// 分组
		Map<String, List<Object>> groupedMapRel = groupByGetMethod(data, members[PARENT_NODE_INDEX]);
		// 赋值转换
		Map<String, List<TreeCheckBoxEntity>> groupedMapJsonTree = assignment(groupedMapRel, members);
		// 递归
		Map<String, List<TreeCheckBoxEntity>> map = recursiveTree(groupedMapJsonTree);

		// 还原数据
		currentKeyFlag = TREE_ROOT_NAME;
		preKeyFlag = TREE_ROOT_NAME;

		List<TreeCheckBoxEntity> jsonList = map.get(currentKeyFlag);

		// 递归数据,组成json map
		return JSONArray.fromObject(jsonList).toString().replace("\"children\":[],", "");
	}


	/** 第0个元素默认是id主键 **/
	private final static Integer PRIMARY_KEY_INDEX = 0;
	/** 第1个元素默认是节点名字 **/
	private final static Integer NODE_NAME_INDEX = 1;
	/** 第2个元素,父节点字段的索引 **/
	private final static Integer PARENT_NODE_INDEX = 2;
	
	private final static Integer NODE_CHECKED = 3;

	/** 树节点的默认状态 **/
	private final static String TREE_NODE_DEFAULT_STATE = "open";

	/**
	 * 此方法用于实际数据和构造的json tree 对象赋值转换
	 * 
	 * @param groupedMap
	 * @param members
	 * @return
	 * @throws SecurityException
	 * @throws IllegalArgumentException
	 * @throws ClassNotFoundException
	 * @throws NoSuchMethodException
	 * @throws IllegalAccessException
	 * @throws InvocationTargetException
	 * @throws IntrospectionException
	 */
	private static Map<String, List<TreeCheckBoxEntity>> assignment(Map<String, List<Object>> groupedMap, String[] members)
			throws SecurityException, IllegalArgumentException, ClassNotFoundException, NoSuchMethodException,
			IllegalAccessException, InvocationTargetException, IntrospectionException {
		Map<String, List<TreeCheckBoxEntity>> groupedMapJsonObj = new HashMap<String, List<TreeCheckBoxEntity>>();
		Iterator<Entry<String, List<Object>>> it = groupedMap.entrySet().iterator();

		while (it.hasNext()) {

			Entry<String, List<Object>> entry = it.next();

			// map->list
			List<Object> valueList = entry.getValue();

			// 新表
			List<TreeCheckBoxEntity> newList = new ArrayList<TreeCheckBoxEntity>();
			for (Object object : valueList) {
				TreeCheckBoxEntity obj = new TreeCheckBoxEntity();

				// id赋值
				String id = getResultByMemberName(object, members[PRIMARY_KEY_INDEX]).toString();
				obj.setId(id);
				// 节点name赋值
				String text = getResultByMemberName(object, members[NODE_NAME_INDEX]).toString();
				obj.setText(text);
				//节点的checked赋值
				String checked = getResultByMemberName(object, members[NODE_CHECKED]).toString();
				obj.setChecked(checked);
				if (entry.getKey().equals(TREE_ROOT_NAME))
					obj.setState(TREE_NODE_DEFAULT_STATE);
				newList.add(obj);
			}

			groupedMapJsonObj.put(entry.getKey(), newList);
		}

		return groupedMapJsonObj;
	}

	/** 根节点的父为空,给它个map key,是这个常量 **/
	private final static String TREE_ROOT_NAME = "root";

	/**
	 * 用xxx类成员来分组 ,返回map数据
	 * 
	 * @param dataList
	 * @param memberName
	 * @return
	 * @throws SecurityException
	 * @throws IllegalArgumentException
	 * @throws ClassNotFoundException
	 * @throws NoSuchMethodException
	 * @throws IllegalAccessException
	 * @throws InvocationTargetException
	 * @throws IntrospectionException
	 */
	public static Map<String, List<Object>> groupByGetMethod(List<Object> dataList, String memberName)
			throws SecurityException, IllegalArgumentException, ClassNotFoundException, NoSuchMethodException,
			IllegalAccessException, InvocationTargetException, IntrospectionException {

		Map<String, List<Object>> groupedMap = new HashMap<String, List<Object>>();

		for (int i = 0; i < dataList.size(); i++) {
			Object value = getResultByMemberName(dataList.get(i), memberName);
			// 获得成员get方法值,分组依据
			String groupTagValue = (value == null || value.equals("")) ? TREE_ROOT_NAME : value.toString();

			// 找数据
			List<Object> findList = groupedMap.get(groupTagValue);

			// 没找到就加数据,增加list
			if (groupedMap.isEmpty() || findList == null) {
				// 做为放在map中的list
				List<Object> tmpList = new ArrayList<Object>();
				tmpList.add(dataList.get(i));
				groupedMap.put(groupTagValue, tmpList);
			}
			// 找到数据就添加数据,增加map
			else {
				findList.add(dataList.get(i));
				// 覆盖map,新list替换旧list
				groupedMap.put(groupTagValue, findList);
			}

		}

		return groupedMap;
	}

	/** 保存遍历list->child时的key **/
	private static String currentKeyFlag = TREE_ROOT_NAME;
	/** 保存遍历list时的当前key **/
	private static String preKeyFlag = TREE_ROOT_NAME;

	/**
	 * 递归树
	 * 
	 * @param groupedMap
	 * @return
	 * @throws SecurityException
	 * @throws IllegalArgumentException
	 * @throws ClassNotFoundException
	 * @throws NoSuchMethodException
	 * @throws IllegalAccessException
	 * @throws InvocationTargetException
	 */
	private static Map<String, List<TreeCheckBoxEntity>> recursiveTree(Map<String, List<TreeCheckBoxEntity>> groupedMap)
			throws SecurityException, IllegalArgumentException, ClassNotFoundException, NoSuchMethodException,
			IllegalAccessException, InvocationTargetException {

		// 复制map
		Map<String, List<TreeCheckBoxEntity>> copyGroupedMap = new HashMap<String, List<TreeCheckBoxEntity>>(groupedMap);

		// 拿到所有的key,key也是父节点id
		Set<String> keys = groupedMap.keySet();

		// 复制一个keys
		Set<String> copyKeys = new HashSet<String>(keys);

		Iterator<Entry<String, List<TreeCheckBoxEntity>>> it = groupedMap.entrySet().iterator();
		while (it.hasNext()) {

			Map.Entry<String, List<TreeCheckBoxEntity>> entry = it.next();
			String currentKey = entry.getKey();

			// 获取根节点，最上的节点
			if (currentKey.equals(currentKeyFlag)) {
				List<TreeCheckBoxEntity> list = entry.getValue();

				// 复制list
				List<TreeCheckBoxEntity> copytList = new ArrayList<TreeCheckBoxEntity>(list);
				for (int i = 0; i < list.size(); i++) {
					// map->list中的每一个id已经拿到
					String id = list.get(i).getId();
					copyKeys.remove(currentKeyFlag);

					// 默认不存在
					boolean flag = false;
					for (Object key : keys) {
						// key和根节点id一样？
						if (key.equals(id)) {
							// 暂存，除去此次遍历的map值,要留下其它的
							Map<String, List<TreeCheckBoxEntity>> removeThisMap = new HashMap<String, List<TreeCheckBoxEntity>>(
									groupedMap);
							removeThisMap.remove(currentKeyFlag);
							// 进行递归
							currentKeyFlag = id;
							preKeyFlag = currentKey;
							Map<String, List<TreeCheckBoxEntity>> childMap = recursiveTree(removeThisMap);
							if (childMap != null) {

								Set<String> childSet = childMap.keySet();
								// 去除包含子节点的map key值
								copyKeys.removeAll(childSet);
								// 主map不要这个值，否则很乱
								// copyGroupedMap.clear() ;
								currentKeyFlag = preKeyFlag;
								// preKeyFlag = id;

								List<TreeCheckBoxEntity> childList = childMap.get(id);
								// 增加子节点
								List<Object> childrenList = new ArrayList<Object>(childList);
								// 改变副本的值
								copytList.get(i).setChildren(childrenList);
								copyGroupedMap.put(currentKey, copytList);
							}
							flag = true;
							// 提前结束循环,一个list就挂一个map
							break;
						}

					}
					// 没有子节点
					if (!flag) {
						List<TreeCheckBoxEntity> tmpList = new ArrayList<TreeCheckBoxEntity>(copyGroupedMap.get(currentKeyFlag));
						tmpList.get(i).setChildren(null);
						// copyGroupedMap.clear() ;
						// TODO @wang'ao 当有一个根节点为空时有问题，不能显示所有根节点
						// Map<String, List<TreeCheckBoxEntity>> tmpMap = new
						// HashMap<String, List<TreeCheckBoxEntity>>(copyGroupedMap) ;
						copyGroupedMap.remove(currentKey);
						copyGroupedMap.put(currentKey, tmpList);
					}
					// currentKey = preKeyFlag;
					preKeyFlag = currentKey;
					currentKeyFlag = preKeyFlag;
				}
				// 提前结束循环while copyKeys
				break;
			}
		}

		return copyGroupedMap;
	}

	/**
	 * 通过成员名获得该方法的get方法的返回值
	 * 
	 * @param thisClass
	 * @param member
	 * @return
	 * @throws ClassNotFoundException
	 * @throws SecurityException
	 * @throws NoSuchMethodException
	 * @throws IllegalArgumentException
	 * @throws IllegalAccessException
	 * @throws InvocationTargetException
	 * @throws IntrospectionException
	 */
	public static Object getResultByMemberName(Object obj, String member)
			throws ClassNotFoundException, SecurityException, NoSuchMethodException, IllegalArgumentException,
			IllegalAccessException, InvocationTargetException, IntrospectionException {

		Class<? extends Object> clazz = obj.getClass();
		Field[] fields = obj.getClass().getDeclaredFields();// 获得属性
		Object o = "";

		for (Field field : fields) {
			String fieldName = field.getName();
			if (member.equals(fieldName)) {
				PropertyDescriptor pd = new PropertyDescriptor(fieldName, clazz);
				Method getMethod = pd.getReadMethod();// 获得get方法
				o = getMethod.invoke(obj);// 执行get方法返回一个Object
				break;
			}

		}
		return o;
	}
}
